use std::{
    ops::{Deref, RangeBounds},
    sync::{
        Arc,
        atomic::{AtomicUsize, Ordering},
    },
    vec::Splice,
};

type StdVec<T> = std::vec::Vec<T>;

#[derive(Debug, Clone)]
pub struct VecItem<T> {
    id: usize,
    ver: usize,
    value: T,
}

#[derive(Debug, Clone, Default)]
pub struct Vec<T> {
    counter: usize,
    value: StdVec<VecItem<T>>,
}

impl<T> Vec<T>
where
    T: Clone,
{
    pub fn new() -> Self {
        Self {
            counter: 0_usize,
            value: StdVec::new(),
        }
    }

    pub fn append(&mut self, other: &mut StdVec<T>) {
        let mut to_append = other
            .iter()
            .enumerate()
            .map(|(i, v)| VecItem {
                id: i + self.counter,
                ver: 0_usize,
                value: v.clone(),
            })
            .collect::<StdVec<VecItem<T>>>();
        self.value.append(&mut to_append);
        self.counter = self.counter + other.len();
    }

    pub fn clear(&mut self) {
        self.value.clear();
    }

    pub fn insert(&mut self, index: usize, element: T) {
        self.value.insert(
            index,
            VecItem {
                id: self.counter,
                ver: 0_usize,
                value: element,
            },
        );
        self.counter = self.counter + 1;
    }

    pub const fn is_empty(&self) -> bool {
        self.value.is_empty()
    }

    pub const fn len(&self) -> usize {
        self.value.len()
    }

    pub fn pop(&mut self) -> Option<VecItem<T>> {
        self.value.pop()
    }

    pub fn push(&mut self, value: T) {
        self.value.push(VecItem {
            id: self.counter,
            ver: 0_usize,
            value,
        });
        self.counter = self.counter + 1;
    }

    pub fn remove(&mut self, index: usize) -> VecItem<T> {
        self.value.remove(index)
    }

    pub fn retain<F>(&mut self, mut f: F)
    where
        F: FnMut(&T) -> bool,
    {
        self.value.retain(|v| f(&v.value));
    }

    pub fn splice<R, I>(
        &mut self,
        range: R,
        replace_with: I,
    ) -> Splice<'_, <StdVec<VecItem<T>> as IntoIterator>::IntoIter>
    where
        R: RangeBounds<usize>,
        I: IntoIterator<Item = T>,
    {
      let r = replace_with.into_iter().collect::<StdVec<T>>();
      let r_1 = r.iter().enumerate().map(|(i, v)| VecItem {
        id: self.counter + i,
        ver: 0_usize,
        value: v.clone(),
      }).collect::<StdVec<VecItem<T>>>();
      self.counter = self.counter + r.len();
      self.value.splice(range, r_1)
    }

    pub fn truncate(&mut self, len: usize) {
        self.value.truncate(len)
    }
}

impl<T> From<StdVec<T>> for Vec<T>
where
    T: Clone,
{
    fn from(value: StdVec<T>) -> Self {
        Self {
            counter: value.len(),
            value: StdVec::from_iter(value.iter().enumerate().map(|(i, v)| VecItem {
                id: i,
                ver: 0_usize,
                value: v.clone(),
            })),
        }
    }
}

impl<T> Deref for Vec<T> {
    type Target = [VecItem<T>];

    fn deref(&self) -> &Self::Target {
        self.value.deref()
    }
}

#[cfg(test)]

mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let a: Vec<usize> = Vec::new();
        assert_eq!(1, 1)
    }
}
